Write-back (지연 쓰기)
1. 개요
Write-back(지연 쓰기)은 데이터를 저장할 때 메인 메모리나 하위 저장소에 즉시 기록하지 않고, 먼저 캐시(Cache)에만 기록한 뒤 특정 시점에 일괄적으로 반영하는 캐싱 전략이다. 이 방식은 쓰기 작업의 빈도가 높을 때 발생하는 I/O 병목 현상을 줄여 시스템의 전반적인 응답 속도를 향상시키는 데 목적이 있다.
2. 동작 원리
Write-back의 핵심은 데이터의 변경 사항을 임시로 보관하고, 실제 저장소로의 쓰기 작업을 최대한 뒤로 미루는 것이다.
캐시의 각 라인(Line) 또는 블록에는 Dirty Bit(더티 비트)라는 상태 플래그가 존재한다.
- Clean (0): 캐시의 데이터와 메인 메모리의 데이터가 동일한 상태.
- Dirty (1): 캐시의 데이터가 수정되었으나, 아직 메인 메모리에 반영되지 않은 상태.
2.2 데이터 쓰기 프로세스
- 쓰기 요청 발생: CPU나 애플리케이션이 특정 주소에 데이터를 쓰고자 한다.
- 캐시 확인: 해당 데이터가 캐시에 있는지 확인한다(Cache Hit/Miss).
- 데이터 처리:
- Cache Hit: 데이터를 캐시에 기록하고, 해당 블록의 Dirty Bit를 1로 설정한다.
- Cache Miss: 필요한 데이터를 메인 메모리에서 캐시로 가져온다(Fetch). 이때 교체 대상이 된 기존 블록의 Dirty Bit가 1이라면, 해당 데이터를 먼저 메인 메모리에 기록(Write-back)한 후 새 데이터를 로드하고 수정한다.
- 완료 응답: 메인 메모리에 기록을 완료하기 전이라도, 캐시 기록이 끝나면 즉시 쓰기 완료 응답을 보낸다.
- 지연 반영: 이후 캐시 교체 알고리즘에 의해 해당 블록이 제거되거나, 강제 플러시(Flush) 명령이 내려질 때 비로소 메인 메모리에 기록된다.
2.3 Write-back 알고리즘 순서도
graph TD
A[쓰기 요청 발생] --> B{캐시 히트 여부?}
B -- Hit --> C[캐시 데이터 수정 및 Dirty Bit = 1 설정]
B -- Miss --> D{교체 대상 블록의 Dirty Bit?}
D -- Dirty == 1 --> E[기존 블록을 메인 메모리에 기록/Write-back]
D -- Dirty == 0 --> F[즉시 교체 가능]
E --> G[새 데이터 캐시 로드 및 수정/Dirty Bit = 1]
F --> G
C --> H[쓰기 완료 응답 반환]
G --> H
Write-through는 캐시에 기록함과 동시에 메인 메모리에도 즉시 기록하는 방식이다.
| 비교 항목 |
Write-through (즉시 반영) |
Write-back (지연 반영) |
| 쓰기 속도 |
느림 (메모리 쓰기 완료까지 대기) |
매우 빠름 (캐시 기록 후 즉시 완료) |
| 데이터 일관성 |
높음 (항상 동일한 상태 유지) |
낮음 (캐시와 메모리 간 불일치 발생)* |
| I/O 트래픽 |
높음 (모든 쓰기 요청이 버스/네트워크 통과) |
낮음 (필요한 시점에만 일괄 전송) |
| 구현 복잡도 |
단순함 |
복잡함 (Dirty Bit 및 교체 로직 필요) |
| 장애 시 위험 |
데이터 손실 위험 적음 |
전원 차단 시 미반영 데이터 손실 위험 |
* 참고: Write-back의 낮은 일관성 문제는 멀티코어 환경에서 캐시 일관성 프로토콜(6절 참조)을 통해 해결한다.
4. 장점 및 성능 최적화 효과
Write-back 전략은 특히 쓰기 집약적인 워크로드에서 극적인 성능 향상을 제공한다.
- 쓰기 지연 시간(Latency) 감소: 상대적으로 속도가 매우 느린 메인 메모리나 디스크 I/O를 기다리지 않고, 고속의 SRAM/DRAM 기반 캐시에서 작업을 마무리하므로 응답 시간이 단축된다.
- I/O 횟수 최적화: 동일한 데이터 블록에 대해 여러 번의 쓰기 작업이 발생하더라도, 최종 결과값만 한 번 메모리에 기록하면 되므로 불필요한 버스 트래픽과 저장소 마모를 줄일 수 있다.
- 대역폭 효율성: 버스(Bus) 점유 시간을 줄여 다른 프로세스나 코어가 메모리 자원을 사용할 수 있는 여유를 제공한다.
5. 데이터 교체 시의 Write-back 시점
캐시는 용량이 제한적이므로 새로운 데이터를 가져오기 위해 기존 데이터를 삭제해야 하는 캐시 교체(Cache Replacement) 상황이 발생한다. 이때 Write-back의 수행 시점이 결정된다.
- 교체 대상 선정: LRU(Least Recently Used) 등의 알고리즘을 통해 제거할 블록을 선정한다.
- 상태 확인: 선정된 블록의 Dirty Bit를 확인한다.
- 조건부 기록:
- Dirty Bit == 0: 데이터가 변경되지 않았으므로 단순히 덮어쓴다(Discard).
- Dirty Bit == 1: 메모리와 데이터가 다르므로, 덮어쓰기 전에 반드시 메인 메모리에 해당 내용을 기록(Write-back)한 후 새 데이터를 로드한다.
6. 캐시 일관성 유지 프로토콜 (Cache Coherency)
멀티코어 환경에서는 각 코어가 개별 캐시를 가지므로, 특정 코어가 Write-back 방식으로 데이터를 수정했을 때 다른 코어가 오래된(Stale) 데이터를 읽는 문제가 발생한다. 이를 해결하기 위해 캐시 일관성 프로토콜을 사용한다.
- Snooping Protocol: 모든 캐시 컨트롤러가 공통 버스를 감시(Snooping)하여, 자신이 가진 데이터가 다른 코어에 의해 수정되었는지 확인하고 상태를 업데이트하는 방식이다.
- MESI 프로토콜: 가장 대표적인 프로토콜로, 캐시 라인의 상태를 4가지로 정의하여 관리한다.
- M (Modified): 데이터가 수정되었으며, 이 캐시만이 최신본을 가지고 있음 (Dirty 상태).
- E (Exclusive): 데이터가 수정되지 않았으며, 이 캐시만이 복사본을 가지고 있음.
- S (Shared): 데이터가 수정되지 않았으며, 여러 캐시가 복사본을 공유하고 있음.
- I (Invalid): 데이터가 유효하지 않음.
7. 잠재적 위험 및 해결 방안
Write-back의 최대 단점은 휘발성으로 인한 데이터 손실 위험이다.
- 위험 요소: 캐시에만 기록된 상태에서 갑작스러운 전원 차단(Power Failure)이나 시스템 크래시가 발생하면, Dirty Bit가 설정된 데이터는 영구 저장소에 기록되지 못하고 소멸한다.
- 보완책:
- BBU (Battery Backup Unit): RAID 컨트롤러 등에 배터리를 장착하여 전원 차단 시에도 캐시 내용을 유지하고, 재부팅 후 메모리에 기록한다.
- NVRAM (Non-Volatile RAM): 비휘발성 메모리를 캐시로 사용하여 전원 없이도 데이터를 보존한다. 예를 들어, 최신 엔터프라이즈 스토리지 컨트롤러는 DRAM 대신 NVRAM이나 NVDIMM을 사용하여 Write-back의 성능 이점과 데이터 안정성을 동시에 확보한다.
- 저널링(Journaling) 및 체크포인트: 변경 이력을 별도의 로그에 먼저 기록하거나, 주기적으로 강제 플러시를 수행하여 손실 범위를 최소화한다.
8. 주요 활용 사례
- CPU L1/L2/L3 캐시: 프로세서의 극단적인 속도 향상을 위해 대부분 Write-back 방식을 채택하며, MESI 프로토콜로 일관성을 유지한다.
- RAID 컨트롤러: 디스크 쓰기 성능을 높이기 위해 온보드 캐시에서 Write-back을 수행하며, 데이터 보호를 위해 BBU나 플래시 백업 모듈을 함께 사용한다.
- 데이터베이스 버퍼 풀(Buffer Pool): MySQL(InnoDB)이나 Oracle 같은 DB 엔진은 디스크 I/O를 줄이기 위해 메모리 상의 페이지를 수정하고, 체크포인트(Checkpoint) 시점에 변경된 페이지(Dirty Page)를 디스크에 일괄 기록한다.
- OS 페이지 캐시(Page Cache): Linux나 Windows 운영체제는 파일 쓰기 요청 시 커널 버퍼에 먼저 기록하고, Linux의
pdflush나 writeback 스레드 같은 백그라운드 프로세스가 주기적으로 디스크에 반영한다.
관련 문서
# Write-back (지연 쓰기)
## 1. 개요
**Write-back**(지연 쓰기)은 데이터를 저장할 때 메인 메모리나 하위 저장소에 즉시 기록하지 않고, 먼저 캐시(Cache)에만 기록한 뒤 특정 시점에 일괄적으로 반영하는 캐싱 전략이다. 이 방식은 쓰기 작업의 빈도가 높을 때 발생하는 I/O 병목 현상을 줄여 시스템의 전반적인 응답 속도를 향상시키는 데 목적이 있다.
## 2. 동작 원리
Write-back의 핵심은 데이터의 변경 사항을 임시로 보관하고, 실제 저장소로의 쓰기 작업을 최대한 뒤로 미루는 것이다.
### 2.1 Dirty Bit의 역할
캐시의 각 라인(Line) 또는 블록에는 **Dirty Bit**(더티 비트)라는 상태 플래그가 존재한다.
- **Clean (0):** 캐시의 데이터와 메인 메모리의 데이터가 동일한 상태.
- **Dirty (1):** 캐시의 데이터가 수정되었으나, 아직 메인 메모리에 반영되지 않은 상태.
### 2.2 데이터 쓰기 프로세스
1. **쓰기 요청 발생:** CPU나 애플리케이션이 특정 주소에 데이터를 쓰고자 한다.
2. **캐시 확인:** 해당 데이터가 캐시에 있는지 확인한다(Cache Hit/Miss).
3. **데이터 처리:**
- **Cache Hit:** 데이터를 캐시에 기록하고, 해당 블록의 **Dirty Bit를 1로 설정**한다.
- **Cache Miss:** 필요한 데이터를 메인 메모리에서 캐시로 가져온다(Fetch). 이때 교체 대상이 된 기존 블록의 Dirty Bit가 1이라면, 해당 데이터를 먼저 메인 메모리에 기록(Write-back)한 후 새 데이터를 로드하고 수정한다.
4. **완료 응답:** 메인 메모리에 기록을 완료하기 전이라도, 캐시 기록이 끝나면 즉시 쓰기 완료 응답을 보낸다.
5. **지연 반영:** 이후 캐시 교체 알고리즘에 의해 해당 블록이 제거되거나, 강제 플러시(Flush) 명령이 내려질 때 비로소 메인 메모리에 기록된다.
### 2.3 Write-back 알고리즘 순서도
```mermaid
graph TD
A[쓰기 요청 발생] --> B{캐시 히트 여부?}
B -- Hit --> C[캐시 데이터 수정 및 Dirty Bit = 1 설정]
B -- Miss --> D{교체 대상 블록의 Dirty Bit?}
D -- Dirty == 1 --> E[기존 블록을 메인 메모리에 기록/Write-back]
D -- Dirty == 0 --> F[즉시 교체 가능]
E --> G[새 데이터 캐시 로드 및 수정/Dirty Bit = 1]
F --> G
C --> H[쓰기 완료 응답 반환]
G --> H
```
## 3. Write-through와의 비교
Write-through는 캐시에 기록함과 동시에 메인 메모리에도 즉시 기록하는 방식이다.
| 비교 항목 | Write-through (즉시 반영) | Write-back (지연 반영) |
| :--- | :--- | :--- |
| **쓰기 속도** | 느림 (메모리 쓰기 완료까지 대기) | 매우 빠름 (캐시 기록 후 즉시 완료) |
| **데이터 일관성** | 높음 (항상 동일한 상태 유지) | 낮음 (캐시와 메모리 간 불일치 발생)* |
| **I/O 트래픽** | 높음 (모든 쓰기 요청이 버스/네트워크 통과) | 낮음 (필요한 시점에만 일괄 전송) |
| **구현 복잡도** | 단순함 | 복잡함 (Dirty Bit 및 교체 로직 필요) |
| **장애 시 위험** | 데이터 손실 위험 적음 | 전원 차단 시 미반영 데이터 손실 위험 |
\* **참고:** Write-back의 낮은 일관성 문제는 멀티코어 환경에서 **캐시 일관성 프로토콜(6절 참조)**을 통해 해결한다.
## 4. 장점 및 성능 최적화 효과
Write-back 전략은 특히 쓰기 집약적인 워크로드에서 극적인 성능 향상을 제공한다.
- **쓰기 지연 시간(Latency) 감소:** 상대적으로 속도가 매우 느린 메인 메모리나 디스크 I/O를 기다리지 않고, 고속의 SRAM/DRAM 기반 캐시에서 작업을 마무리하므로 응답 시간이 단축된다.
- **I/O 횟수 최적화:** 동일한 데이터 블록에 대해 여러 번의 쓰기 작업이 발생하더라도, 최종 결과값만 한 번 메모리에 기록하면 되므로 불필요한 버스 트래픽과 저장소 마모를 줄일 수 있다.
- **대역폭 효율성:** 버스(Bus) 점유 시간을 줄여 다른 프로세스나 코어가 메모리 자원을 사용할 수 있는 여유를 제공한다.
## 5. 데이터 교체 시의 Write-back 시점
캐시는 용량이 제한적이므로 새로운 데이터를 가져오기 위해 기존 데이터를 삭제해야 하는 **캐시 교체(Cache Replacement)** 상황이 발생한다. 이때 Write-back의 수행 시점이 결정된다.
1. **교체 대상 선정:** LRU(Least Recently Used) 등의 알고리즘을 통해 제거할 블록을 선정한다.
2. **상태 확인:** 선정된 블록의 Dirty Bit를 확인한다.
3. **조건부 기록:**
- **Dirty Bit == 0:** 데이터가 변경되지 않았으므로 단순히 덮어쓴다(Discard).
- **Dirty Bit == 1:** 메모리와 데이터가 다르므로, 덮어쓰기 전에 반드시 메인 메모리에 해당 내용을 기록(Write-back)한 후 새 데이터를 로드한다.
## 6. 캐시 일관성 유지 프로토콜 (Cache Coherency)
멀티코어 환경에서는 각 코어가 개별 캐시를 가지므로, 특정 코어가 Write-back 방식으로 데이터를 수정했을 때 다른 코어가 오래된(Stale) 데이터를 읽는 문제가 발생한다. 이를 해결하기 위해 **캐시 일관성 프로토콜**을 사용한다.
- **Snooping Protocol:** 모든 캐시 컨트롤러가 공통 버스를 감시(**Snooping**)하여, 자신이 가진 데이터가 다른 코어에 의해 수정되었는지 확인하고 상태를 업데이트하는 방식이다.
- **MESI 프로토콜:** 가장 대표적인 프로토콜로, 캐시 라인의 상태를 4가지로 정의하여 관리한다.
- **M (Modified):** 데이터가 수정되었으며, 이 캐시만이 최신본을 가지고 있음 (Dirty 상태).
- **E (Exclusive):** 데이터가 수정되지 않았으며, 이 캐시만이 복사본을 가지고 있음.
- **S (Shared):** 데이터가 수정되지 않았으며, 여러 캐시가 복사본을 공유하고 있음.
- **I (Invalid):** 데이터가 유효하지 않음.
## 7. 잠재적 위험 및 해결 방안
Write-back의 최대 단점은 **휘발성**으로 인한 데이터 손실 위험이다.
- **위험 요소:** 캐시에만 기록된 상태에서 갑작스러운 전원 차단(Power Failure)이나 시스템 크래시가 발생하면, Dirty Bit가 설정된 데이터는 영구 저장소에 기록되지 못하고 소멸한다.
- **보완책:**
- **BBU (Battery Backup Unit):** RAID 컨트롤러 등에 배터리를 장착하여 전원 차단 시에도 캐시 내용을 유지하고, 재부팅 후 메모리에 기록한다.
- **NVRAM (Non-Volatile RAM):** 비휘발성 메모리를 캐시로 사용하여 전원 없이도 데이터를 보존한다. 예를 들어, 최신 엔터프라이즈 스토리지 컨트롤러는 DRAM 대신 **NVRAM**이나 **NVDIMM**을 사용하여 Write-back의 성능 이점과 데이터 안정성을 동시에 확보한다.
- **저널링(Journaling) 및 체크포인트:** 변경 이력을 별도의 로그에 먼저 기록하거나, 주기적으로 강제 플러시를 수행하여 손실 범위를 최소화한다.
## 8. 주요 활용 사례
- **CPU L1/L2/L3 캐시:** 프로세서의 극단적인 속도 향상을 위해 대부분 Write-back 방식을 채택하며, MESI 프로토콜로 일관성을 유지한다.
- **RAID 컨트롤러:** 디스크 쓰기 성능을 높이기 위해 온보드 캐시에서 Write-back을 수행하며, 데이터 보호를 위해 BBU나 플래시 백업 모듈을 함께 사용한다.
- **데이터베이스 버퍼 풀(Buffer Pool):** **MySQL(InnoDB)**이나 **Oracle** 같은 DB 엔진은 디스크 I/O를 줄이기 위해 메모리 상의 페이지를 수정하고, 체크포인트(Checkpoint) 시점에 변경된 페이지(Dirty Page)를 디스크에 일괄 기록한다.
- **OS 페이지 캐시(Page Cache):** **Linux**나 **Windows** 운영체제는 파일 쓰기 요청 시 커널 버퍼에 먼저 기록하고, Linux의 `pdflush`나 `writeback` 스레드 같은 백그라운드 프로세스가 주기적으로 디스크에 반영한다.
## 관련 문서
- [Write-through]( #)
- [Cache Coherency]( #)
- [LRU Algorithm]( #)
- [MESI Protocol]( #)